package compound.repository

import pattern.PatternHelper
import compound.repository.entries.Compound
import util.ConvertInchi

class SearchService {

    //association to the lookup service
    LookupService lookupService

    /**
     * reference to the searchable lucene
     * service
     */
    def searchableService = null


    boolean transactional = true

    /**
     * executes a generic search against the datbase dependend of regular expressions
     */
    def searchGeneric(String value, Map params = [:]) {

        log.info("generic search string: ${value}")

        Map result = params

        log.info("received: $params")

        Long total = 0

        def temp = null
        if (value.matches(PatternHelper.STD_INCHI_KEY_PATTERN)) {
            log.debug "is std inchi code -> using limited search"
            temp = lookupService.lookupByInchiKey(value, params)

            total = lookupService.countlookupByInchiKey(value, params)
        }
        else if (value.matches(PatternHelper.STD_INCHI_PATTERN)) {
            log.debug "is std inchi -> using limited search"

            //optimizations, inchikeys can be indexed
            def key = ConvertInchi.convertInchiToKey(value)

            temp = lookupService.lookupByInchiKey(key, params)
            total = lookupService.countlookupByInchiKey(key, params)

        }
        else if (value.matches(PatternHelper.CAS_PATTERN)) {
            log.debug "is cas -> using limited search"

            temp = lookupService.lookupByCas(value, params)
            total = lookupService.countlookupByCas(value, params)

        }
        else if (value.matches(PatternHelper.KEGG_PATTERN)) {

            log.debug "is kegg -> using limited search"

            temp = lookupService.lookupByKegg(value, params)
            total = lookupService.countlookupByKegg(value, params)

        }
        else if (value.matches(PatternHelper.LIPID_MAPS_PATTERN)) {

            log.debug "is lipid maps -> using limited search"

            temp = lookupService.lookupByLipidMapId(value, params)
            total = lookupService.countlookupByLipidMapId(value, params)

        }
        else if (value.matches(PatternHelper.HMDB_PATTERN)) {

            log.debug "is hmdb -> using limited search"

            temp = lookupService.lookupByHMDB(value, params)
            total = lookupService.countlookupByHMDB(value, params)

        }
        else if (value.matches(PatternHelper.SID_PATTERN)) {

            log.debug "is sid -> using limited search"

            temp = lookupService.lookupBySID(Integer.parseInt(value.split(":")[1]), params)
            total = lookupService.countlookupBySID(Integer.parseInt(value.split(":")[1]), params)

        }
        else if (value.matches(PatternHelper.CID_PATTERN)) {

            log.debug "is cid -> using limited search"

            temp = lookupService.lookupByCID(Integer.parseInt(value.split(":")[1]), params)
            total = lookupService.countlookupByCID(Integer.parseInt(value.split(":")[1]), params)

        }
        else {

            log.debug "nothing detected -> using name search"

            temp = lookupService.lookupByName(value, params)
            total = lookupService.countlookupByName(value, params)

        }


        result.total = total

        log.info("query generic result total count: ${result.total}")

        if (temp instanceof Collection) {
            result.results = temp
        }
        else {
            result.results = [temp]
        }

        log.info("query generic result: ${result}")

        return result
    }

    /**
     * executes a lucene/compass search
     */
    def textSearch(String query, Map params = [:]) {
        log.info("lucene search string: ${query}")

        try {
            Map result = Compound.search(query, params)

            log.info("query result: ${result}")

            if (result.results.isEmpty()) {
                log.debug("nothing found, fallback and execute generic search...")
                return searchGeneric(query, params)
            }
            else {
                log.debug "query was executed using lucene"
                return result
            }
        }
        catch (Exception e) {
            log.info "lucene error occured (${e.getMessage()}), fall back to generic search"

            return searchGeneric(query, params)

        }
    }
}
